package messages

import (
	"context"
	"github.com/go-kit/kit/endpoint"
)

type Endpoints struct {
	MessageSearchEndpoint  endpoint.Endpoint
	MessageContextEndpoint endpoint.Endpoint
	SmartAlarmEndpoint     endpoint.Endpoint
	KeywordAlarmEndpoint   endpoint.Endpoint
	SearchFileEndpoint     endpoint.Endpoint
	SetTagEndpoint         endpoint.Endpoint
	FileTravelEndpoint     endpoint.Endpoint
}

func MakeServerEndpoints(s Service) Endpoints {
	return Endpoints{
		MessageSearchEndpoint:  makeMessageSearchEndpoint(s),
		MessageContextEndpoint: makeMessageContextEndpoint(s),
		SmartAlarmEndpoint:     makeSmartAlarmEndpoint(s),
		KeywordAlarmEndpoint:   makeKeywordAlarmEndpoint(s),
		SearchFileEndpoint:     makeSearchFileEndpoint(s),
		SetTagEndpoint:         makeSetTagEndpoint(s),
		FileTravelEndpoint:     makeFileTravelEndpoint(s),
	}
}

func makeFileTravelEndpoint(s Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(fileTravelRequest)
		data, err := s.FileTravel(ctx, req.Id)
		if err != nil {
			return fileTravelResponse{Error: err.Error()}, nil
		}
		return fileTravelResponse{Data: data}, nil
	}
}

func makeSetTagEndpoint(s Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(setTagRequest)
		data, err := s.SetTag(ctx, req)
		if err != nil {
			return setTagResponse{Error: err.Error()}, nil
		}
		return setTagResponse{Data: data}, nil
	}
}

func makeSearchFileEndpoint(s Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		req := request.(searchFileRequest)
		count, data, err := s.SearchFile(ctx, req)
		if err != nil {
			return searchFileResponse{Error: err.Error()}, nil
		}
		return searchFileResponse{Count: count, Data: data}, nil
	}
}

func makeSmartAlarmEndpoint(s Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		req := request.(alarmMessageRequest)
		count, data, haveNext, headData, tailData, err := s.AlarmMessage(ctx, true, req)
		if err != nil {
			return alarmMessageResponse{Error: err.Error()}, nil
		}
		return alarmMessageResponse{Count: count, Data: data, HaveNext: haveNext, HeadData: headData, TailData: tailData}, nil
	}
}

func makeKeywordAlarmEndpoint(s Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		req := request.(alarmMessageRequest)
		count, data, haveNext, headData, tailData, err := s.AlarmMessage(ctx, false, req)
		if err != nil {
			return alarmMessageResponse{Error: err.Error()}, nil
		}
		return alarmMessageResponse{Count: count, Data: data, HaveNext: haveNext, HeadData: headData, TailData: tailData}, nil
	}
}

func makeMessageContextEndpoint(s Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		req := request.(messageContextRequest)
		data, err := s.MessageContext(ctx, req)
		if err != nil {
			return messageContextResponse{Error: err.Error()}, nil
		}
		return messageContextResponse{Data: data}, nil
	}
}

func makeMessageSearchEndpoint(s Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		req := request.(messageSearchRequest)
		count, data, haveNext, headData, tailData, err := s.MessageSearch(ctx, req)
		if err != nil {
			return messageSearchResponse{Error: err.Error()}, nil
		}
		return messageSearchResponse{Count: count, Data: data, HaveNext: haveNext, HeadData: headData, TailData: tailData}, nil
	}
}

type fileTravelRequest struct {
	Id string `json:"id"`
}

type fileTravelResponse struct {
	Data  []Message `json:"data"`
	Error string    `json:"error"`
}

type setTagRequest struct {
	Id   string   `json:"id"`
	Tags []string `json:"tags"`
}

type tagInfo struct {
	setTagRequest
}

type setTagResponse struct {
	Data  []tagInfo `json:"data"`
	Error string    `json:"error"`
}

type searchFileRequest struct {
	StartTimestamp int64    `json:"startTimestamp"`
	EndTimestamp   int64    `json:"endTimestamp"`
	Types          []string `json:"types"`
	Name           string   `json:"name"`
	Size           int64    `json:"size"`
	Page           int64    `json:"page"`
}

type searchFileResponse struct {
	Count int64  `json:"count"`
	Data  []File `json:"data,omitempty"`
	Error string `json:"error,omitempty"`
}

type messageContextRequest struct {
	Before int64   `json:"before"`
	After  int64   `json:"after"`
	Data   Message `json:"data"`
}

type messageContextResponse struct {
	Data  []Message `json:"data,omitempty"`
	Error string    `json:"error,omitempty"`
}

type alarmMessageRequest struct {
	StartTimestamp int64   `json:"startTimestamp"`
	EndTimestamp   int64   `json:"endTimestamp"`
	Keyword        string  `json:"keyword"`
	Topic          string  `json:"topic"`
	CollectorId    string  `json:"collectorId"`
	CollectorUser  string  `json:"collectorUser"`
	CollectorOrgan string  `json:"collectorOrgan"`
	DataSource     string  `json:"dataSource"`
	OrderBy        string  `json:"orderBy"`
	Size           int64   `json:"size"`
	Skip           int64   `json:"skip"`
	Data           Message `json:"data"`
}

type alarmMessageResponse struct {
	Count    int64       `json:"count"`
	HaveNext bool        `json:"haveNext"`
	HeadData Message     `json:"headData,omitempty"`
	TailData Message     `json:"tailData,omitempty"`
	Data     [][]Message `json:"data,omitempty"`
	Error    string      `json:"error,omitempty"`
}

type messageSearchRequest struct {
	StartTimestamp int64    `json:"startTimestamp"`
	EndTimestamp   int64    `json:"endTimestamp"`
	Keyword        string   `json:"keyword"`
	CollectorId    string   `json:"collectorId"`
	CollectorUser  string   `json:"collectorUser"`
	CollectorOrgan string   `json:"collectorOrgan"`
	CategoryId     string   `json:"categoryId"`
	DataSource     string   `json:"dataSource"`
	Chatroom       string   `json:"chatroom"`
	ChatroomIds    []string `json:"-"` // 用来保存Category对应的群id数组
	Member         string   `json:"member"`
	Size           int64    `json:"size"`
	Skip           int64    `json:"skip"`
	Data           Message  `json:"data"`
}

type messageSearchResponse struct {
	Count    int64       `json:"count"`
	HeadData Message     `json:"headData,omitempty"`
	TailData Message     `json:"tailData,omitempty"`
	HaveNext bool        `json:"haveNext"`
	Data     [][]Message `json:"data,omitempty"`
	Error    string      `json:"error,omitempty"`
}
